<?php
/**
 * Profiler class
 * This allows us to take snapshots of application speed and
 * memory usage at any point within our application.
 * This class also contains an error collector
 * All of this is rudimentary. As we build the first couple of
 * applications with this framework, we will add more
 * functionality, extensibility and more dynamic (and prettier!)
 * output
 *
 * Nothing should be performed unless the defined variable: DEBUG
 * is set to true (boolean, defined in /config/core.config.php)
 */
class Profiler
{
	/**
	 * Reference to the main object
	 */
	private $main;

	/**
	 * This is the primary container for all logged items
	 *
	 * @var array
	 */
	private $_logCollection = array();

	/**
	 * This is the counter for all logged speed records
	 *
	 * @var int
	 */
	private $_speedLogCount = 0;

	/**
	 * This is the counter for all logged memory records
	 *
	 * @var int
	 */
	private $_memoryLogCount = 0;

	/**
	 * This is the counter for all logged errors
	 *
	 * @var int
	 */
	private $_errorLogCount = 0;

	public function __construct($main)
	{
		$this->main = $main;
	}

	/**
	 * This function logs how long the application has been
	 * running up to the specified point.
	 *
	 * @param string $script
	 * @param int $line
	 * @return boolean
	 */
	public function logSpeed($script, $line, $note='')
	{
		if (DEBUG === true){
			$this->_logCollection['speed'][$this->_speedLogCount]['script'] = $script;
			$this->_logCollection['speed'][$this->_speedLogCount]['line'] = $line;
			$this->_logCollection['speed'][$this->_speedLogCount]['note'] = $note;
			$this->_logCollection['speed'][$this->_speedLogCount]['time'] = microtime(true);

			$this->_speedLogCount++;
		}

		return true;
	}

	/**
	 * This function logs how much memory the application has
	 * been utilizing up to the specified point.
	 *
	 * @param string $script
	 * @param int $line
	 * @return boolean
	 */
	public function logMemory($script, $line, $note='')
	{
		if (DEBUG === true){
			$this->_logCollection['memory'][$this->_memoryLogCount]['script'] = $script;
			$this->_logCollection['memory'][$this->_memoryLogCount]['line'] = $line;
			$this->_logCollection['memory'][$this->_memoryLogCount]['note'] = $note;
			$this->_logCollection['memory'][$this->_memoryLogCount]['memory'] = memory_get_usage();

			$this->_memoryLogCount++;
		}

		return true;
	}

	/**
	 * This function logs all non-error related possible
	 * logging functions at one, without having to call them
	 * individually
	 *
	 * @param string $script
	 * @param unknown_type $line
	 * @return unknown
	 */
	public function logAll($script, $line, $note='')
	{
		$this->logSpeed($script, $line, $note);
		$this->logMemory($script, $line, $note);

		return true;
	}

	/**
	 * Log an application-defined error
	 *
	 * @param string $script
	 * @param int $line
	 * @param string $error
	 * @return boolean
	 */
	public function logError($script, $line, $error, $note)
	{
		if (DEBUG === true){
			$this->_logCollection['error'][$this->_errorLogCount]['script'] = $script;
			$this->_logCollection['error'][$this->_errorLogCount]['line'] = $line;
			$this->_logCollection['error'][$this->_errorLogCount]['error'] = $error;
			$this->_logCollection['error'][$this->_errorLogCount]['note'] = $note;

			$this->_errorLogCount++;
		}
	}

	/**
	 * Echo out all collected data in a readable format
	 *
	 * @return boolean
	 */
	public function output()
	{
		echo "<table style=\"margin: 0px; padding: 0px;\">\n";
		echo "	<tr>\n";
		echo "		<td colspan=\"4\" align=\"left\" width=\"100%\" style=\"font-size: 16px; font-weight: bold;\">ENVIRONMENT DATA</td>\n";
		echo "	</tr>\n";
		echo "	<tr>\n";
		echo "		<td style=\"font-weight:bold; padding-right: 30px;\">Request Time</td>\n";
		echo "		<td style=\"text-align: left;\">" . date("l, F jS @ g:h A", $_SERVER['REQUEST_TIME']) . " ({$_SERVER['REQUEST_TIME']})</td>\n";
		echo "	</tr>\n";
		echo "	<tr>\n";
		echo "		<td style=\"font-weight:bold; padding-right: 30px;\">Request URI</td>\n";
		echo "		<td style=\"text-align: left;\">{$_SERVER['REQUEST_URI']}</td>\n";
		echo "	</tr>\n";

		if (!empty($_SERVER['HTTP_REFERER'])){
			echo "	<tr>\n";
			echo "		<td style=\"font-weight:bold; padding-right: 30px;\">HTTP Referer</td>\n";
			echo "		<td style=\"text-align: left;\">{$_SERVER['HTTP_REFERER']}</td>\n";
			echo "	</tr>\n";
		}

		echo "	<tr>\n";
		echo "		<td style=\"font-weight:bold; padding-right: 30px;\">HTTP User Agent</td>\n";
		echo "		<td style=\"text-align: left;\">{$_SERVER['HTTP_USER_AGENT']}</td>\n";
		echo "	</tr>\n";
		echo "	<tr>\n";
		echo "		<td style=\"font-weight:bold; padding-right: 30px;\">Script Filename</td>\n";
		echo "		<td style=\"text-align: left;\">{$_SERVER['SCRIPT_FILENAME']}</td>\n";
		echo "	</tr>\n";
		echo "</table>\n";
		echo "<br /><br />\n";


		/**
		 * Output any logged errors, if any
		 */
		if (!empty($this->_logCollection['error'])){
			echo '<br /><b>ERRORS</b><br />';
			for ($i=0; $i<$this->_errorLogCount; $i++)
			{
				echo str_replace(INCLUDES_ROOT_FULL_SERVER_PATH, '', $this->_logCollection['error'][$i]['script']) . " :: line {$this->_logCollection['error'][$i]['line']} :: Error: {$this->_logCollection['error'][$i]['error']}";
				echo (!empty($this->_logCollection['error'][$i]['note'])) ? " :: Note: {$this->_logCollection['error'][$i]['note']}" : '';
				echo "<br />\n";
			}
		}

		/**
		 * Output the speed records
		 */
		if (!empty($this->_logCollection['speed'])){
			$tdHeaderStyle = " style=\"padding: 3px 20px 3px 0; text-align: left; font-weight: bold;\"";
			$tdStyle = " style=\"padding: 3px 20px 3px 3px; text-align: left; border-bottom: solid 1px #9f9f9f; border-right: solid 1px #9f9f9f;\"";

			echo "<table style=\"margin: 0px; padding: 0px;\">\n";
			echo "	<tr>\n";
			echo "		<td colspan=\"4\" align=\"left\" width=\"100%\" style=\"font-size: 16px; font-weight: bold;\">SPEED MEASUREMENTS</td>\n";
			echo "	</tr>\n";
			echo "	<tr>\n";
			echo "		<td{$tdHeaderStyle}>Script</td>\n";
			echo "		<td{$tdHeaderStyle}>Line</td>\n";
			echo "		<td{$tdHeaderStyle}>Speed (seconds)</td>\n";
			echo "		<td{$tdHeaderStyle}>Note</td>\n";
			echo "	</tr>\n";

			foreach ($this->_logCollection['speed'] as $entry)
			{
				$time = number_format(($entry['time'] - $this->_logCollection['speed'][0]['time']),4);

				echo "	<tr>\n";
				echo "		<td{$tdStyle}>" . str_replace(INCLUDES_ROOT_FULL_SERVER_PATH, '', $entry['script']) . "</td>\n";
				echo "		<td{$tdStyle}>{$entry['line']}</td>\n";
				echo "		<td{$tdStyle}>{$time}</td>\n";
				echo "		<td{$tdStyle}>{$entry['note']}</td>\n";
				echo "	</tr>\n";
			}

			echo "	<tr>\n";
			echo "		<td colspan=\"4\" align=\"left\" width=\"100%\">TOTAL EXECUTION TIME: " . (number_format((microtime(true) - $this->_logCollection['speed'][0]['time']),4)) . " SECONDS</td>\n";
			echo "	</tr>\n";
			echo "</table>\n";
		}

		/**
		 * Output the memory records
		 */
		if (!empty($this->_logCollection['memory'])){
			$tdHeaderStyle = " style=\"padding: 3px 20px 3px 0; text-align: left; font-weight: bold;\"";
			$tdStyle = " style=\"padding: 3px 20px 3px 3px; text-align: left; border-bottom: solid 1px #9f9f9f; border-right: solid 1px #9f9f9f;\"";

			echo "<br /><br />\n";
			echo "<table style=\"margin: 0px; padding: 0px;\">\n";
			echo "	<tr>\n";
			echo "		<td colspan=\"4\" align=\"left\" width=\"100%\" style=\"font-size: 16px; font-weight: bold;\">MEMORY USAGE</td>\n";
			echo "	</tr>\n";
			echo "	<tr>\n";
			echo "		<td{$tdHeaderStyle}>Script</td>\n";
			echo "		<td{$tdHeaderStyle}>Line</td>\n";
			echo "		<td{$tdHeaderStyle}>Memory (KB)</td>\n";
			echo "		<td{$tdHeaderStyle}>Note</td>\n";
			echo "	</tr>\n";

			foreach ($this->_logCollection['memory'] as $entry)
			{
				$memory = number_format(($entry['memory'] / 1024), 2);

				echo "	<tr>\n";
				echo "		<td{$tdStyle}>" . str_replace(INCLUDES_ROOT_FULL_SERVER_PATH, '', $entry['script']) . "</td>\n";
				echo "		<td{$tdStyle}>{$entry['line']}</td>\n";
				echo "		<td{$tdStyle}>{$memory}</td>\n";
				echo "		<td{$tdStyle}>{$entry['note']}</td>\n";
				echo "	</tr>\n";
			}

			echo "	<tr>\n";
			echo "		<td colspan=\"4\" align=\"left\" width=\"100%\">PEAK MEMORY USAGE: " . number_format((memory_get_peak_usage() / 1024),2) . "KB</td>\n";
			echo "	</tr>\n";
			echo "</table>\n";
		}

		/**
		 * Output all session vars
		 */
		if (!empty($_SESSION)){
			echo '<br /><br /><b>SESSION VARIABLES</b><br />';
			echo '<pre>' . print_r($_SESSION, true) . '</pre>';
		}

		/**
		 * Output all contents of the main object
		 */
		echo '<br /><br /><b>MAIN OBJECT</b><br />';
		echo '<pre>' . print_r($this->main, true) . '</pre>';

		return true;
	}
}